/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.form.compat2.layouts; import java.awt.*; import org.openide.nodes.Sheet; import org.openide.nodes.PropertySupport; import org.openide.util.NbBundle; import org.netbeans.modules.form.util2.NbVersion; import org.netbeans.modules.form.util2.NbVersionNotCompatibleException; import org.openide.nodes.Node; import org.openide.nodes.PropertySupport; import org.netbeans.modules.form.*; /** A design-time support for FlowLayout. * * @author Ian Formanek */ final public class DesignFlowLayout extends DesignLayout implements java.io.Externalizable { /** A JDK 1.1 serial version UID */ static final long serialVersionUID = -8528054575046773692L; /** Netbeans class version */ public static final NbVersion nbClassVersion = new NbVersion (1, 0); /* Layout Properties */ public static final String PROP_ALIGNMENT = "alignment"; // NOI18N public static final String PROP_HGAP = "horizontalGap"; // NOI18N public static final String PROP_VGAP = "verticalGap"; // NOI18N /* Default Property values */ private static final int DEFAULT_VGAP = 5; private static final int DEFAULT_HGAP = 5; private static final int DEFAULT_ALIGNMENT = FlowLayout.CENTER; private Node.Property alignmentProperty; private Node.Property hgapProperty; private Node.Property vgapProperty; /** bundle to obtain text information from */ private static final java.util.ResourceBundle bundle = NbBundle.getBundle (DesignFlowLayout.class); /** icons for the Layout. */ private static final Image icon = Toolkit.getDefaultToolkit ().getImage ( DesignFlowLayout.class.getResource ("/org/netbeans/modules/form/resources/palette/flowLayout.gif")); // NOI18N private static final Image icon32 = Toolkit.getDefaultToolkit ().getImage ( DesignFlowLayout.class.getResource ("/org/netbeans/modules/form/resources/palette/flowLayout32.gif")); // NOI18N /** The Sheet holding layout property sheet */ private Sheet sheet; /** Assigns this DesignLayout to the specified RADVisualContainer. * @param cont The RADVisualContainer that represents a container that will be * managed by this layout or null as a notification that this layout * is not a designLayout for its current container anymore */ public void setRADContainer (RADVisualContainer cont) { super.setRADContainer(cont); if (cont != null) { getContainer().setLayout (realLayout = new FlowLayout()); realLayout.setAlignment (alignment); realLayout.setHgap (hgap); realLayout.setVgap (vgap); } } /** Method which allows the design layout to provide list of properties to be saved with the form. * @return list of Node.Property objects */ public java.util.List getChangedProperties () { getPropertySet (); // enforce creation of properties java.util.ArrayList list = new java.util.ArrayList (3); if (alignment != DEFAULT_ALIGNMENT) list.add (alignmentProperty); if (hgap != DEFAULT_HGAP) list.add (hgapProperty); if (vgap != DEFAULT_VGAP) list.add (vgapProperty); return list; } /** Method which is called after the layout is loaded with the form to initialize its properties. * @param cahngedProperties map of <String, Object> pairs, where the String is a name of property and the Object its value */ public void initChangedProperties (java.util.Map changedProperties) { Integer hgapVal = (Integer)changedProperties.get (PROP_HGAP); if (hgapVal != null) hgap = hgapVal.intValue (); Integer vgapVal = (Integer)changedProperties.get (PROP_VGAP); if (vgapVal != null) vgap = vgapVal.intValue (); Integer alignmentVal = (Integer)changedProperties.get (PROP_ALIGNMENT); if (alignmentVal != null) alignment = alignmentVal.intValue (); } /** An icon of the design-layout. This icon will be used on the ComponentPalette * for this layout's item. * @param type the desired type of the icon (BeanInfo.ICON_???) * @return layout's icon. */ public Image getIcon(int type) { if ((type == java.beans.BeanInfo.ICON_COLOR_16x16) || (type == java.beans.BeanInfo.ICON_MONO_16x16)) return icon; else return icon32; } /** @return an index that would be used to insert a new component to * specified position. The index is an first index after the existing component * under the posistion. */ /* private int findIndexForPosition (Point position) { Component[] components = getContainer ().getComponents (); if (components.length == 0) return 0; // find first component index with y-pos > position.y // this will become the boundary int biggerY = -1; for (int i = 0; i < components.length; i++) if (components[i].getLocation ().y > position.y) { biggerY = i; break; } // no component is below this position if (biggerY == -1) { // 1. check for adding below all components // find if the position is below lower edge of the last row of components int i; for (i = components.length -1; i >= 0; i--) if (components[i].getLocation ().y + components[i].getSize ().height > position.y) { break; } if (i == -1) // all components are above, so we are adding to the end return components.length; // 2. check for adding right of all components // to prevent the whole traversal, we check separately if (components [components.length - 1].getLocation ().x + components [components.length - 1].getSize ().width < position.x) return components.length; biggerY = components.length; } // find the component with the right x coordinates // we are searching from the last component with bigger y coordinates // to find the bottom-most component for (int i = biggerY - 1; i >= 0; i--) { Component comp = components [i]; if (comp.getLocation ().x + comp.getSize ().width < position.x) return i + 1; } return components.length; } */ /** Returns a constraint to be used for adding a component to the * specified position (e.g. in BorderLayout, the "North", "South", ... * will be determined by the position in the container). * The default implementation just returns the default constraints. * A special constraints object will be returned for layouts that * wish to set the position&size of the components rather than add * with constraints. * @param position The position within the container for which the * constraints should be returned. */ public DesignLayout.ConstraintsDescription getConstraintsDescription(Point position) { return new FlowConstraintsDescription(); } /** A display name of the layout will be used for displaying the layout in * the components hierarchy during design-time. * @return layout's display name. */ public String getDisplayName() { return "FlowLayout"; // NOI18N } /** Returns the global layout's properties (i.e. the properties * that are not different for different components in the layout * @return the global layout properties */ public Node.PropertySet[] getPropertySet() { if (sheet == null) { sheet = new Sheet (); Sheet.Set set = Sheet.createPropertiesSet (); set.put (alignmentProperty = new PropertySupport.ReadWrite ( PROP_ALIGNMENT, Integer.TYPE, bundle.getString("PROP_flow_alignment"), bundle.getString("HINT_flow_alignment") ) { public Object getValue () { return new Integer(alignment); } public void setValue (Object val) throws IllegalArgumentException { if (val instanceof Integer) { int newValue = ((Integer)val).intValue(); if (newValue == alignment) return; int oldValue = alignment; alignment = newValue; realLayout.setAlignment (alignment); getContainer().invalidate(); getContainer().validate(); firePropertyChange (null, PROP_ALIGNMENT, new Integer(oldValue), new Integer(alignment)); } else throw new IllegalArgumentException(); } /** Editor for alignment */ public java.beans.PropertyEditor getPropertyEditor () { return new FlowAlignmentEditor (); } public boolean supportsDefaultValue () { return true; } public void restoreDefaultValue () { try { setValue (new Integer (DEFAULT_ALIGNMENT)); } catch (IllegalArgumentException e) { } // ignore failure } } ); set.put (hgapProperty = new PropertySupport.ReadWrite ( PROP_HGAP, Integer.TYPE, bundle.getString("PROP_flow_hgap"), bundle.getString("HINT_flow_hgap") ) { public Object getValue () { return new Integer(hgap); } public void setValue (Object val) throws IllegalArgumentException { if (val instanceof Integer) { int newValue = ((Integer)val).intValue(); if (newValue == hgap) return; int oldValue = hgap; hgap = newValue; realLayout.setHgap (hgap); getContainer().invalidate(); getContainer().validate(); firePropertyChange (null, PROP_HGAP, new Integer(oldValue), new Integer(hgap)); } else throw new IllegalArgumentException(); } public boolean supportsDefaultValue () { return true; } public void restoreDefaultValue () { try { setValue (new Integer (DEFAULT_HGAP)); } catch (IllegalArgumentException e) { } // ignore failure } } ); set.put (vgapProperty = new PropertySupport.ReadWrite ( PROP_VGAP, Integer.TYPE, bundle.getString("PROP_flow_vgap"), bundle.getString("HINT_flow_vgap") ) { public Object getValue () { return new Integer(vgap); } public void setValue (Object val) throws IllegalArgumentException { if (val instanceof Integer) { int newValue = ((Integer)val).intValue(); if (newValue == vgap) return; int oldValue = vgap; vgap = newValue; realLayout.setVgap (vgap); getContainer().invalidate(); getContainer().validate(); firePropertyChange (null, PROP_VGAP, new Integer(oldValue), new Integer(vgap)); } else throw new IllegalArgumentException(); } public boolean supportsDefaultValue () { return true; } public void restoreDefaultValue () { try { setValue (new Integer (DEFAULT_VGAP)); } catch (IllegalArgumentException e) { } // ignore failure } } ); sheet.put (set); } return sheet.toArray (); } /** Returns a class of the layout that this DesignLayout represents (e.g. * returns FlowLayout.class from DesignFlowLayout). * @return a class of the layout represented by this DesignLayout or null if the * design layout does not represent a "real" layout (e.g. support layouts for JTabbedPane, ...) */ public Class getLayoutClass() { return FlowLayout.class; } // ----------------------------------------------------------------------------- // Code generation /** Generates the code for initialization of this layout, e.g. panel1.setLayout (new BorderLayout ());. * @param cont The container that is managed by this layout * @return the init code for the layout or null if it should not be generated */ public String generateInitCode(RADVisualContainer cont) { LayoutManager defaultLM = null; try { Container defaultCont = (Container)BeanSupport.getDefaultInstance (cont.getBeanClass ()); if (defaultCont != null) defaultLM = defaultCont.getLayout (); } catch (Exception e) { if (Boolean.getBoolean ("netbeans.debug.exceptions")) e.printStackTrace (); // NOI18N // ok, no default } if (defaultLM != null) { if (defaultLM.getClass ().equals (FlowLayout.class)) { if ((((FlowLayout)defaultLM).getHgap () == hgap) && (((FlowLayout)defaultLM).getVgap () == vgap) && (((FlowLayout)defaultLM).getAlignment () == alignment)) { return null; // the default layout is the same as current settings => no need to generate layout } } } StringBuffer buf = new StringBuffer(); String containerName = createContainerGenName(cont); buf.append(containerName); if (complexConstructor ()) { buf.append("setLayout (new java.awt.FlowLayout ("); // NOI18N buf.append (alignment); buf.append (", "); // NOI18N buf.append (hgap); buf.append (", "); // NOI18N buf.append (vgap); buf.append ("));\n"); // NOI18N } else { buf.append("setLayout (new java.awt.FlowLayout ());\n"); // NOI18N } return buf.toString(); } private boolean complexConstructor () { return (alignment != DEFAULT_ALIGNMENT) || (vgap != DEFAULT_VGAP) || (hgap != DEFAULT_HGAP); } /** Generates the code for adding specified component to this layout. * @param comp The component to be added to this layout * @param cont The container that is managed by this layout */ public String generateComponentCode(RADVisualContainer cont, RADVisualComponent comp) { StringBuffer buf = new StringBuffer(); buf.append(createContainerGenName(cont)); buf.append("add ("); // NOI18N buf.append(comp.getName()); buf.append(");\n"); // NOI18N return buf.toString(); } // ----------------------------------------------------------------------------- // Serialization /** Writes the object to the stream. * @param oo output stream to write to * @exception IOException Includes any I/O exceptions that may occur */ public void writeExternal (java.io.ObjectOutput oo) throws java.io.IOException { // store version oo.writeObject (nbClassVersion); oo.writeInt (alignment); oo.writeInt (vgap); oo.writeInt (hgap); } /** Reads the object from stream. * @param oi input stream to read from * @exception IOException Includes any I/O exceptions that may occur * @exception ClassNotFoundException if the class of the read object is not found */ public void readExternal (java.io.ObjectInput oi) throws java.io.IOException, ClassNotFoundException { org.netbeans.modules.form.FormUtils.DEBUG(">> DesignFlowLayout: readExternal: START"); // NOI18N // check the version NbVersion classVersion = (NbVersion) oi.readObject (); if (!nbClassVersion.isCompatible (classVersion)) throw new NbVersionNotCompatibleException (classVersion, nbClassVersion); alignment = oi.readInt (); vgap = oi.readInt (); hgap = oi.readInt (); org.netbeans.modules.form.FormUtils.DEBUG("<< DesignFlowLayout: readExternal: END"); // NOI18N } // ----------------------------------------------------------------------------- // constraints innerclass /** The ConstraintsDescription class encapsulates constraints data and * operations on a constraints that will be used for adding components * to the layout. */ final public static class FlowConstraintsDescription extends DesignLayout.ConstraintsDescription implements java.io.Externalizable { /** A JDK 1.1. serial version UID */ static final long serialVersionUID = 7307795910510106204L; /** Netbeans class version */ public static final NbVersion nbClassVersion = new NbVersion (1, 0); /** Returns a textual descriptions of constraints represented by this * class. E.g. for BorderLayout, it is a text "Center" or "North". * @return textual descriptions of the constraints */ public String getConstraintsString() { return bundle.getString ("MSG_flow_add"); } // ----------------------------------------------------------------------------- // Serialization /** Writes the object to the stream. * @param oo output stream to write to * @exception IOException Includes any I/O exceptions that may occur */ public void writeExternal (java.io.ObjectOutput oo) throws java.io.IOException { // store version oo.writeObject (nbClassVersion); } /** Reads the object from stream. * @param oi input stream to read from * @exception IOException Includes any I/O exceptions that may occur * @exception ClassNotFoundException if the class of the read object is not found */ public void readExternal (java.io.ObjectInput oi) throws java.io.IOException, ClassNotFoundException { org.netbeans.modules.form.FormUtils.DEBUG(">> FlowConstraintsDescription: readExternal: START"); // NOI18N // check the version NbVersion classVersion = (NbVersion) oi.readObject (); if (!nbClassVersion.isCompatible (classVersion)) throw new NbVersionNotCompatibleException (classVersion, nbClassVersion); org.netbeans.modules.form.FormUtils.DEBUG("<< FlowConstraintsDescription: readExternal: END"); // NOI18N } } final public static class FlowAlignmentEditor extends java.beans.PropertyEditorSupport { /** Display Names for alignment. */ private static final String[] names = { bundle.getString ("VALUE_flowalignment_center"), bundle.getString ("VALUE_flowalignment_left"), bundle.getString ("VALUE_flowalignment_right"), }; /** @return names of the possible directions */ public String[] getTags () { return names; } /** @return text for the current value */ public String getAsText () { int value = ((Integer)getValue ()).intValue (); if (value == FlowLayout.CENTER) return names[0]; else if (value == FlowLayout.LEFT) return names[1]; else if (value == FlowLayout.RIGHT) return names[2]; else return null; } /** Setter. * @param str string equal to one value from directions array */ public void setAsText (String str) { if (names[0].equals (str)) setValue (new Integer (FlowLayout.CENTER)); else if (names[1].equals (str)) setValue (new Integer (FlowLayout.LEFT)); else if (names[2].equals (str)) setValue (new Integer (FlowLayout.RIGHT)); } public String getJavaInitializationString () { int value = ((Integer)getValue ()).intValue (); switch (value) { case FlowLayout.LEFT : return "java.awt.FlowLayout.LEFT"; // NOI18N case FlowLayout.RIGHT: return "java.awt.FlowLayout.RIGHT"; // NOI18N default: return "java.awt.FlowLayout.CENTER"; // NOI18N } } } // ----------------------------------------------------------------------------- // private area /** The real FlowLayout LayoutManager that works in real-layout mode*/ transient private FlowLayout realLayout; /** The alignment property */ private int alignment = DEFAULT_ALIGNMENT; /** The vertical gap property */ private int vgap = DEFAULT_VGAP; /** The horizontal gap property */ private int hgap = DEFAULT_HGAP; } /* * Log * 18 Gandalf 1.17 1/12/00 Ian Formanek NOI18N * 17 Gandalf 1.16 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 16 Gandalf 1.15 9/24/99 Ian Formanek Smarter code generation * - fixes bug 4016 - The setLayout code should not be generated if the * layout is already set on the container to prevent loosing components * already on the panel. * 15 Gandalf 1.14 9/24/99 Ian Formanek generateInitCode method * clarified * 14 Gandalf 1.13 7/31/99 Ian Formanek Cleaned up comments * 13 Gandalf 1.12 7/23/99 Ian Formanek Fixed bug 2679 - An * exception in the compiler, after compiling ClockFrame, part2 or * MemoryView * 12 Gandalf 1.11 7/13/99 Ian Formanek LayoutProperties support * restoring default value, added changedProperties to support XML * Serialization * 11 Gandalf 1.10 6/27/99 Ian Formanek Removed indent parameter * from code generation methods * 10 Gandalf 1.9 6/10/99 Ian Formanek Regeneration on layout * changes * 9 Gandalf 1.8 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 8 Gandalf 1.7 5/15/99 Ian Formanek * 7 Gandalf 1.6 5/14/99 Ian Formanek * 6 Gandalf 1.5 5/12/99 Ian Formanek * 5 Gandalf 1.4 5/11/99 Ian Formanek Build 318 version * 4 Gandalf 1.3 5/10/99 Ian Formanek * 3 Gandalf 1.2 5/4/99 Ian Formanek package change * (formeditor -> ..) * 2 Gandalf 1.1 3/29/99 Ian Formanek Uses FormUtils.DEBUG to * print messages * 1 Gandalf 1.0 3/28/99 Ian Formanek * $ */